package com.weifly.weistock.web.controller;

import com.weifly.weistock.core.common.Result;
import com.weifly.weistock.core.market.StockMarketService;
import com.weifly.weistock.core.market.StockPriceDto;
import com.weifly.weistock.core.util.WeistockUtils;
import com.weifly.weistock.core.util.grid.GridPriceGenerator;
import com.weifly.weistock.core.util.grid.GridPricePoint;
import com.weifly.weistock.trade.config.AccountConfigDto;
import com.weifly.weistock.trade.config.StockConfigDto;
import com.weifly.weistock.trade.monitor.StockMonitorDto;
import com.weifly.weistock.trade.monitor.vo.StatusVO;
import com.weifly.weistock.trade.monitor.StockMonitorService;
import com.weifly.weistock.trade.trade.StockOrderInfo;
import com.weifly.weistock.trade.trade.StockTradeService;
import com.weifly.weistock.web.controller.vo.StockConfigVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * 股票
 *
 * @author weifly
 * @since 2019/1/30
 */
@Controller
@RequestMapping(value = "/stock")
public class StockController {

    private Logger log = LoggerFactory.getLogger(StockController.class);

    @Autowired
    private StockMonitorService stockMonitorService;

    @Autowired
    private StockMarketService stockMarketService;

    @Autowired
    private StockTradeService stockTradeService;

    /**
     * 股票首页
     */
    @RequestMapping(value = "/index")
    public String index(HttpServletRequest request, HttpServletResponse response) {
        return "stock/stock";
    }

    /**
     * 股票监控
     */
    @RequestMapping(value = "/monitor")
    public String monitor(HttpServletRequest request, HttpServletResponse response) {
        return "stock/monitor";
    }

    /**
     * 加载股票状态
     */
    @ResponseBody
    @RequestMapping("/loadStockStatus")
    public Result loadStockStatus(HttpServletRequest request){
        try{
            StatusVO stockMonitorInfo = this.stockMonitorService.calcMonitorInfo();
            return Result.createSuccessResult(stockMonitorInfo);
        }catch(Exception e){
            log.error("加载股票状态出错", e);
            return Result.createErrorResult("加载股票状态出错", null);
        }
    }

    /**
     * 编辑股票账号
     */
    @RequestMapping(value = "/editAccount")
    public String editAccount(HttpServletRequest request){
        AccountConfigDto accountConfig = this.stockMonitorService.getAccountConfig();
        if(accountConfig!=null){
            request.setAttribute("accountConfig", WeistockUtils.toJsonString(accountConfig));
        }
        return "stock/editAccount";
    }

    /**
     * 更新股票账号
     */
    @ResponseBody
    @RequestMapping("/updateAccount")
    public Result updateAccount(AccountConfigDto account){
        try{
            if(account==null){
                return Result.createErrorResult("缺少配置");
            }
            if(account.getQsid()==null || account.getQsid()<0){
                return Result.createErrorResult("缺少配置：券商id");
            }
            if(StringUtils.isBlank(account.getServerIp())){
                return Result.createErrorResult("缺少配置：交易服务器ip");
            }
            if(account.getServerPort()==null || account.getServerPort()<=0){
                return Result.createErrorResult("缺少配置：交易服务器port");
            }
            if(StringUtils.isBlank(account.getVersion())){
                return Result.createErrorResult("缺少配置：版本");
            }
            if(account.getYybID()==null){
                return Result.createErrorResult("缺少配置：营业部id");
            }
            if(account.getAccountType()==null){
                return Result.createErrorResult("缺少配置：登录账户类别");
            }
            if(StringUtils.isBlank(account.getAccountNo())){
                return Result.createErrorResult("缺少配置：客户账号");
            }
            if(StringUtils.isBlank(account.getTradeAccount())){
                return Result.createErrorResult("缺少配置：交易账号");
            }
            if(StringUtils.isBlank(account.getJyPassword())){
                return Result.createErrorResult("缺少配置：交易密码");
            }

            this.stockMonitorService.updateAccountConfig(account, true);
            return Result.createSuccessResult(null);
        }catch(Exception e){
            log.error("更新账号出错", e);
            return Result.createErrorResult("更新账号出错", null);
        }
    }

    /**
     * 编辑股票配置
     */
    @RequestMapping(value = "/editStockConfig")
    public String editStockConfig(HttpServletRequest request){
        String stockCode = request.getParameter("code");
        if(StringUtils.isNotBlank(stockCode)){
            StockConfigDto targetConfig = null;
            for(StockMonitorDto monitorDto : this.stockMonitorService.getStockList()){
                if(stockCode.equals(monitorDto.getStockConfig().getStockCode())){
                    targetConfig = monitorDto.getStockConfig();
                    break;
                }
            }
            if(targetConfig!=null){
                StockConfigVO configVO = this.convertConfig(targetConfig);
                request.setAttribute("stockConfig", WeistockUtils.toJsonString(configVO));
            }
        }
        return "stock/editStockConfig";
    }

    private StockConfigVO convertConfig(StockConfigDto configDto){
        StockConfigVO configVO = new StockConfigVO();
        configVO.setStockCode(configDto.getStockCode());
        configVO.setStockName(configDto.getStockName());
        configVO.setExchangeId(configDto.getExchangeId());
        configVO.setOpen(configDto.getOpen());
        configVO.setBasePrice(configDto.getBasePrice());
        configVO.setTradeUnit(configDto.getTradeUnit());
        configVO.setStep(configDto.getStep());
        configVO.setCreditBuy(configDto.getCreditBuy());

        List<Double> priceList = configDto.getGridPriceList();
        List<GridPricePoint> pointList = new ArrayList<>();
        for(Double price : priceList){
            GridPricePoint point = new GridPricePoint();
            point.setPrice(price);
            pointList.add(point);
        }
        if(pointList.size()>1){
            GridPricePoint currPoint = pointList.get(0);
            for(int i=1;i<pointList.size();i++){
                GridPricePoint nextPoint = pointList.get(i);
                double diff = WeistockUtils.subtract(currPoint.getPrice(), nextPoint.getPrice());
                double step = WeistockUtils.divide(WeistockUtils.multi(diff, 100), nextPoint.getPrice());
                currPoint.setDiff(diff);
                currPoint.setStep(step);
                currPoint = nextPoint;
            }
        }
        configVO.setGridPriceList(pointList);
        return configVO;
    }

    /**
     * 根据股票代码，生成股票配置
     */
    @ResponseBody
    @RequestMapping("/makeStockConfig")
    public Result makeStockConfig(HttpServletRequest request){
        try{
            String stockCode = request.getParameter("stockCode");
            if(StringUtils.isBlank(stockCode)){
                return Result.createErrorResult("缺少配置：股票代码");
            }
            String stepStr = request.getParameter("step");
            if(StringUtils.isBlank(stepStr)){
                return Result.createErrorResult("缺少配置：网格间距");
            }
            double step = Double.parseDouble(stepStr);
            if(step<1 || step>10){
                return Result.createErrorResult("网格间距应大于等于1，小于等于10");
            }

            StockPriceDto stockPrice = this.stockMarketService.getStockPrice(stockCode);
            if(stockPrice==null){
                return Result.createErrorResult("无法获得股票价格");
            }

            StockConfigVO stockConfig = new StockConfigVO();
            stockConfig.setStockCode(stockCode);
            stockConfig.setStockName(stockPrice.getName());
            stockConfig.setExchangeId(stockPrice.getExchangeId());

            // 基准价格
            String basePriceStr = request.getParameter("basePrice");
            double basePrice;
            if(StringUtils.isBlank(basePriceStr)){
                basePrice = stockPrice.getNowPrice();
            }else{
                basePrice = Double.parseDouble(basePriceStr);
            }
            stockConfig.setBasePrice(basePrice);
            // 网格价格列表
            GridPriceGenerator generator = new GridPriceGenerator();
            generator.setMinPrice(WeistockUtils.multi(basePrice, 0.5));
            generator.setMaxPrice(WeistockUtils.multi(basePrice, 1.8));
            generator.setBasePrice(basePrice);
            generator.setMinStepPrice(stockPrice.getMinStepPrice());
            generator.setStep(step);
            List<GridPricePoint> gridPriceList = generator.generateGridPriceList();
            stockConfig.setGridPriceList(gridPriceList);

            return Result.createSuccessResult(stockConfig);
        }catch(Exception e){
            log.error("生成股票配置出错", e);
            return Result.createErrorResult("生成股票配置出错");
        }
    }

    /**
     * 更新股票配置
     */
    @ResponseBody
    @RequestMapping("/updateStockConfig")
    public Result updateStockConfig(HttpServletRequest request){
        try{
            StockConfigDto stockConfig = new StockConfigDto();
            String stockName = request.getParameter("stockName");
            if(StringUtils.isBlank(stockName)){
                return Result.createErrorResult("缺少配置：股票名称");
            }
            stockConfig.setStockName(stockName);

            String stockCode = request.getParameter("stockCode");
            if(StringUtils.isBlank(stockCode)){
                return Result.createErrorResult("缺少配置：股票代码");
            }
            stockConfig.setStockCode(stockCode);

            String exchangeId = request.getParameter("exchangeId");
            if(StringUtils.isBlank(exchangeId)){
                return Result.createErrorResult("缺少配置：交易所ID");
            }
            stockConfig.setExchangeId(exchangeId);

            String open = request.getParameter("open");
            stockConfig.setOpen("true".equals(open));

            String basePrice = request.getParameter("basePrice");
            if(StringUtils.isBlank(basePrice)){
                return Result.createErrorResult("缺少配置：基准价格");
            }
            stockConfig.setBasePrice(Double.valueOf(basePrice));

            String tradeUnit = request.getParameter("tradeUnit");
            if(StringUtils.isBlank(tradeUnit)){
                return Result.createErrorResult("缺少配置：每次交易量");
            }
            stockConfig.setTradeUnit(Integer.valueOf(tradeUnit));

            String stepStr = request.getParameter("step");
            if(StringUtils.isBlank(stepStr)){
                return Result.createErrorResult("缺少配置：网格间距");
            }
            double step = Double.parseDouble(stepStr);
            if(step<1 || step>10){
                return Result.createErrorResult("网格间距应大于等于1，小于等于10");
            }
            stockConfig.setStep(step);

            String creditBuy = request.getParameter("creditBuy");
            stockConfig.setCreditBuy("true".equals(creditBuy));

            String gridPrice = request.getParameter("gridPrice");
            if(StringUtils.isBlank(gridPrice)){
                return Result.createErrorResult("缺少配置：网格价格列表");
            }
            String[] prices = gridPrice.split(",");
            for(String onePrice : prices){
                stockConfig.getGridPriceList().add(Double.valueOf(onePrice));
            }

            this.stockMonitorService.updateStockConfig(stockConfig);
            return Result.createSuccessResult(null);
        }catch(Exception e){
            log.error("更新股票出错", e);
            return Result.createErrorResult("更新股票出错");
        }
    }

    /**
     * 获得当日委托列表
     */
    @ResponseBody
    @RequestMapping("/getOrderList")
    public Result getOrderList(HttpServletRequest request) {
        try{
            List<StockOrderInfo> orderList = this.stockTradeService.getOrderList();
            return Result.createSuccessResult(orderList);
        }catch(Exception e){
            log.error("更新股票出错", e);
            return Result.createErrorResult("更新股票出错");
        }
    }
}
